package com.example.simplerpc.client.net;

import com.example.simplerpc.common.service.Service;
import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.CountDownLatch;

/**
 * @Classname: NettyNetClient
 * @Description:
 * @Author: Stonffe
 * @Date: 2022/12/19 9:13
 */
@Slf4j
public class NettyNetClient implements NetClient {
    /**
     *  发送请求
     * @param data
     * @param service
     * @return
     * @throws InterruptedException
     */
    @Override
    public byte[] sendRequest(byte[] data, Service service) throws InterruptedException {
        String[] address = service.getAddress().split(":");
        String serverAddr = address[0];
        String serverPort = address[1];
        SendHandler sendHandler = new SendHandler(data);
        byte[] respData;
        NioEventLoopGroup group = new NioEventLoopGroup();
        try {
            Bootstrap bootstrap = new Bootstrap();
            bootstrap.group(group).channel(NioSocketChannel.class).option(ChannelOption.TCP_NODELAY,true)
                    .handler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel socketChannel) throws Exception {
                            ChannelPipeline pipeline = socketChannel.pipeline();
                            pipeline.addLast(sendHandler);
                        }
                    });
            bootstrap.connect(serverAddr,Integer.parseInt(serverPort)).sync();
            respData = ((byte[]) sendHandler.respData());
            log.info("得到回复：{}",respData);
        }finally {
            group.shutdownGracefully();
        }

        return respData;
    }
    public class SendHandler extends ChannelInboundHandlerAdapter {
        private CountDownLatch ctl;
        private Object readMsg = null;
        private byte[] data;
        public SendHandler(byte[] data){
            ctl = new CountDownLatch(1);
            this.data = data;
        }

        /**
         * 发送数据
         * @param ctx
         * @throws Exception
         */
        @Override
        public void channelActive(ChannelHandlerContext ctx) throws Exception {
            log.info("成功连接到服务端：{}",ctx);
            ByteBuf buffer = Unpooled.buffer(data.length);
            buffer.writeBytes(data);
            log.info("客户端发送数据：{}",buffer);
            ctx.writeAndFlush(buffer);
        }

        /**
         *  读取数据释放cd锁
         * @param ctx
         * @param msg
         * @throws Exception
         */
        @Override
        public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
            log.info("客户端收到信息：{}",msg);
            ByteBuf byteBuf = (ByteBuf) msg;
            byte[] resp = new byte[byteBuf.readableBytes()];
            byteBuf.readBytes(resp);
            readMsg = resp;
            ctl.countDown();
        }
        public Object respData() throws InterruptedException{
            ctl.await();
            return readMsg;
        }
        @Override
        public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
            ctx.flush();
        }

        @Override
        public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
            cause.printStackTrace();
            ctx.close();
        }
    }
}
